﻿using LayoutHelpers.Primitives;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace LayoutHelpers
{
  public class LayoutableUserControl : UserControl
  {
    public static readonly DependencyProperty LayoutRulesProperty = DependencyProperty.Register("LayoutRules", typeof(List<ILayoutRule>), typeof(LayoutableUserControl), new PropertyMetadata(null, OnLayoutRulesPropertyChanged));
    public List<ILayoutRule> LayoutRules
    {
      get { return GetValue(LayoutRulesProperty) as List<ILayoutRule>; }
      private set { SetValue(LayoutRulesProperty, value); }
    }

    static void OnLayoutRulesPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
      var _this = source as LayoutableUserControl;
      if (_this.rootRuleChanging)
        return;

      var rootRule = _this.RootLayoutRuleGroup;
      if (rootRule != null)
        rootRule.Rules = e.NewValue as List<ILayoutRule>;
    }

    public static readonly DependencyProperty RootLayoutRuleGroupTypeProperty = DependencyProperty.Register("RootLayoutRuleGroupType", typeof(RuleGroupType), typeof(LayoutableUserControl), new PropertyMetadata(RuleGroupType.AllMatches, OnRootLayoutRuleGroupTypePropertyChanged));
    public RuleGroupType RootLayoutRuleGroupType
    {
      get { return (RuleGroupType)GetValue(RootLayoutRuleGroupTypeProperty); }
      set { SetValue(RootLayoutRuleGroupTypeProperty, value); }
    }

    static void OnRootLayoutRuleGroupTypePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
      var _this = source as LayoutableUserControl;
      if (_this.rootRuleChanging)
        return;

      var rootRule = _this.RootLayoutRuleGroup;
      if (rootRule != null)
        rootRule.ExecutionType = (RuleGroupType)e.NewValue;
    }

    public static readonly DependencyProperty RootLayoutRuleGroupProperty = DependencyProperty.Register("RootLayoutRuleGroup", typeof(LayoutRuleGroup), typeof(LayoutableUserControl), new PropertyMetadata(null, OnRootLayoutRuleGroupPropertyChanged));
    public LayoutRuleGroup RootLayoutRuleGroup
    {
      get { return GetValue(RootLayoutRuleGroupProperty) as LayoutRuleGroup; }
      set { SetValue(RootLayoutRuleGroupProperty, value); }
    }

    bool rootRuleChanging = false;
    static void OnRootLayoutRuleGroupPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
      var _this = source as LayoutableUserControl;
      _this.rootRuleChanging = true;
      _this.LayoutRules = (e.NewValue as LayoutRuleGroup).Rules;
      _this.RootLayoutRuleGroupType = (e.NewValue as LayoutRuleGroup).ExecutionType;
      _this.rootRuleChanging = false;
    }

    public LayoutableUserControl()
    {
      SetValue(RootLayoutRuleGroupProperty, new LayoutRuleGroup());
    }

    public void InvalidateLayoutRules()
    {
      lastSize = default(Size);
    }

    Size lastSize;

    protected override Size MeasureOverride(Size availableSize)
    {
      if (lastSize != availableSize)
      {
        RunLayoutRules(this, availableSize, RootLayoutRuleGroup);
      }

      lastSize = availableSize;
      return base.MeasureOverride(availableSize);
    }

    internal static void RunLayoutRules(FrameworkElement element, Size availableSize, LayoutRuleGroup layoutRules)
    {
      if (layoutRules != null && layoutRules.Evaluate(availableSize) && layoutRules.CanExecute(element))
        layoutRules.Execute(element);
    }
  }
}